#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
using namespace std;

// int cnt = 0;
void catchSig(int signum)
{
    cout << "进程捕捉到了一个信号,正在处理中: " << signum << " Pid: " << getpid() << endl;
    // cout << "final cnt: " << cnt << " 信号: " << signum << " Pid: " << getpid() << endl;
    // alarm(1); // 重设闹钟 -> 定时器 -> 你可以实现任意任务
}

// static void Usage(string proc)
// {
//     cout << "Usage:\r\n\t" << proc << " signumber processid" << endl;
// }

static void showPending(sigset_t &pending)
{
    for (int sig = 1; sig <= 31; sig++)
    {
        if (sigismember(&pending, sig)) //在信号集里,输出1
            cout << "1";
        else
            cout << "0";
    }
    cout << endl;
}

int main(int argc, char *argv[])
{
    // 0. 方便测试，捕捉2号信号，不要退出
    signal(2, catchSig);
    // 1. 定义信号集对象
    sigset_t bset, obset; // b是block,o是old
    sigset_t pending;
    // 2. 初始化
    sigemptyset(&bset);
    sigemptyset(&obset);
    sigemptyset(&pending);
    // 3. 添加要进行屏蔽的信号
    sigaddset(&bset, 2 /*SIGINT*/);
    // 4. 设置set到内核中对应的进程内部[默认情况进程不会对任何信号进行block]
    int n = sigprocmask(SIG_BLOCK, &bset, &obset); // sigset_t变量和老的sigset_t变量
    assert(n == 0); // sigprocmask成功了返回0
    (void)n; // 强转一下,防止relese下出现变量未被使用的警告

    cout << "block 2 号信号成功..., pid: " << getpid() << endl;
    // 5. 重复打印当前进程的pending信号集
    int count = 0;
    while (true)
    {
        // 5.1 获取当前进程的pending信号集
        sigpending(&pending);
        // 5.2 显示pending信号集中的没有被递达的信号
        showPending(pending);
        sleep(1);
        count++;
        if (count == 20) // 20秒后恢复2号信号的block,1->0
        {
            // 默认情况下，恢复对于2号信号的block的时候，确实会进行递达
            // 但是2号信号的默认处理动作是终止进程,需要对2号信号进行捕捉->第0步
            cout << "开始解除对于2号信号的block" << endl;
            int n = sigprocmask(SIG_SETMASK, &obset, nullptr); // 用老的set恢复
            assert(n == 0);
            (void)n;
            cout << "解除对于2号信号的block成功" << endl;
        }
    }

    // cout << "my pid: " << getpid() << endl;
    // for (int sig = 1; sig <= 31; sig++)
    // {
    //     signal(sig, catchSig);
    // }

    // while (true)
    // {
    //     sleep(1);
    // }

    // signal(SIGSEGV, catchSig);
    // cout << "my pid: " << getpid() << endl;
    // int *p = nullptr;
    // *p = 100;

    // while (true)
    // {
    //     sleep(1);
    // }

    // signal(SIGFPE,catchSig);

    // int cnt = 0;
    // while(true)
    // {
    //     cout << "正在运行的进程" << cnt++ << endl;

    //     int result = 7;
    //     result /= 0;
    //     sleep(1);
    // }

    // signal(SIGALRM,catchSig);
    // alarm(1); // 先设定了一个闹钟，这个闹钟一旦触发，就自动移除了

    // while(true)
    // {
    //     ++cnt;
    // }

    // cout << "我开始运行咯" << endl;
    // sleep(1);
    // abort(); // 通常用来进行终止进程。等于raise(6) 等于kill(getpid(), 6)
    // // raise(9); // 等于kill(getpid(), 8)
    // cout << "运行结束咯" << endl;

    // if(argc != 3) // ./mykill 9 pid
    // {
    //     Usage(argv[0]);
    //     exit(1);
    // }

    // int signumber = atoi(argv[1]);
    // int procid = atoi(argv[2]); // 获取两个命令行参数并转化

    // int ret = kill(procid, signumber);
    // if(ret != 0)
    // {
    //     cerr << errno << ": " << strerror(errno) << endl;
    // }

    // signal(SIGINT, catchSig); // 特定信号的处理动作,一般只有一个
    // signal(SIGQUIT, catchSig);
    // // signal函数，仅仅是修改进程对特定信号的后续处理动作，不是直接调用对应的处理动作
    // // 如果后续没有任何SIGINT信号产生，catchSig永远也不会被调用
    // while(1)
    // {
    //     cout << "I am a process,my pid: " << getpid()<< endl;
    //     sleep(1);
    // }
    return 0;
}